package com.pet.platform.service.impl;


import com.pet.platform.common.PageResult;
import com.pet.platform.dto.AppointmentDTO;
import com.pet.platform.dto.AppointmentQueryDTO;
import com.pet.platform.entity.Appointment;
import com.pet.platform.entity.Pet;
import com.pet.platform.entity.Service;
import com.pet.platform.entity.User;
import com.pet.platform.exception.BusinessException;
import com.pet.platform.mapper.AppointmentMapper;
import com.pet.platform.mapper.PetMapper;
import com.pet.platform.mapper.ServiceMapper;
import com.pet.platform.mapper.UserMapper;
import com.pet.platform.service.AppointmentService;
import com.pet.platform.util.SecurityUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Component
public class AppointmentServiceImpl implements AppointmentService {

    @Resource
    private AppointmentMapper appointmentMapper;
    
    @Resource
    private ServiceMapper serviceMapper;
    
    @Resource
    private PetMapper petMapper;
    
    @Resource
    private UserMapper userMapper;

    @Override
    public Appointment findById(Long id) {
        Appointment appointment = appointmentMapper.findById(id);
        if (appointment == null) {
            throw new BusinessException("预约不存在");
        }
        
        // 检查权限
        if (!SecurityUtil.isAdmin() && !appointment.getUserId().equals(SecurityUtil.getCurrentUserId())) {
            throw new BusinessException("无权访问该预约");
        }
        
        return appointment;
    }

    @Override
    public PageResult<AppointmentDTO> findPage(AppointmentQueryDTO queryDTO) {
        // 如果不是管理员，只能查看自己的预约
        if (!SecurityUtil.isAdmin()) {
            queryDTO.setUserId(SecurityUtil.getCurrentUserId());
        }
        
        // 计算分页参数
        int offset = (queryDTO.getPageNum() - 1) * queryDTO.getPageSize();
        int limit = queryDTO.getPageSize();
        
        // 查询数据
        List<Appointment> appointments = appointmentMapper.findPage(queryDTO, offset, limit);
        long total = appointmentMapper.count(queryDTO);
        
        // 转换为DTO
        List<AppointmentDTO> appointmentDTOs = appointments.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
        
        return new PageResult<>(total, appointmentDTOs);
    }

    @Override
    @Transactional
    public void create(AppointmentDTO appointmentDTO) {
        // 验证服务是否存在
        Service service = serviceMapper.findById(appointmentDTO.getServiceId());
        if (service == null) {
            throw new BusinessException("服务不存在");
        }
        
        // 验证服务是否可用
        if (service.getStatus() != 1) {
            throw new BusinessException("该服务已暂停预约");
        }
        
        // 验证宠物是否存在
        Pet pet = petMapper.findById(appointmentDTO.getPetId());
        if (pet == null) {
            throw new BusinessException("宠物不存在");
        }
        
        // 验证宠物是否属于当前用户
        if (!pet.getOwnerId().equals(SecurityUtil.getCurrentUserId())) {
            throw new BusinessException("不能为他人的宠物预约服务");
        }
        
        // 验证预约时间是否有效
        if (appointmentDTO.getAppointmentTime().isBefore(LocalDateTime.now())) {
            throw new BusinessException("预约时间不能早于当前时间");
        }
        
        // 检查是否有时间冲突
        if (checkTimeConflict(appointmentDTO.getServiceId(), appointmentDTO)) {
            throw new BusinessException("该时间段已被预约，请选择其他时间");
        }
        
        // 创建预约
        Appointment appointment = new Appointment();
        BeanUtils.copyProperties(appointmentDTO, appointment);
        
        // 设置默认值
        appointment.setUserId(SecurityUtil.getCurrentUserId());
        appointment.setStatus("PENDING");
        appointment.setCreatedTime(LocalDateTime.now());
        appointment.setUpdatedTime(LocalDateTime.now());
        
        appointmentMapper.insert(appointment);
    }

    @Override
    @Transactional
    public void update(Long id, AppointmentDTO appointmentDTO) {
        // 验证预约是否存在
        Appointment appointment = findById(id);
        
        // 只有管理员或预约本人可以修改
        if (!SecurityUtil.isAdmin() && !appointment.getUserId().equals(SecurityUtil.getCurrentUserId())) {
            throw new BusinessException("无权修改该预约");
        }
        
        // 已完成或已取消的预约不能修改
        if ("COMPLETED".equals(appointment.getStatus()) || "CANCELLED".equals(appointment.getStatus())) {
            throw new BusinessException("已完成或已取消的预约不能修改");
        }
        
        // 更新数据
        appointment.setPetId(appointmentDTO.getPetId());
        appointment.setAppointmentTime(appointmentDTO.getAppointmentTime());
        appointment.setRemark(appointmentDTO.getRemark());
        appointment.setUpdatedTime(LocalDateTime.now());
        
        appointmentMapper.update(appointment);
    }

    @Override
    @Transactional
    public void delete(Long id) {
        // 验证预约是否存在
        Appointment appointment = findById(id);
        
        // 只有管理员或预约本人可以删除
        if (!SecurityUtil.isAdmin() && !appointment.getUserId().equals(SecurityUtil.getCurrentUserId())) {
            throw new BusinessException("无权删除该预约");
        }
        
        appointmentMapper.delete(id);
    }

    @Override
    @Transactional
    public void updateStatus(Long id, String status) {
        // 验证预约是否存在
        Appointment appointment = findById(id);
        
        // 验证状态是否有效
        if (!isValidStatus(status)) {
            throw new BusinessException("无效的状态值");
        }
        
        // 只有管理员可以确认和完成预约
        if ((status.equals("CONFIRMED") || status.equals("COMPLETED")) && !SecurityUtil.isAdmin()) {
            throw new BusinessException("只有管理员可以确认或完成预约");
        }
        
        // 如果是取消预约，检查是否有权限
        if (status.equals("CANCELLED") && !SecurityUtil.isAdmin() && !appointment.getUserId().equals(SecurityUtil.getCurrentUserId())) {
            throw new BusinessException("无权取消该预约");
        }
        
        // 已取消的预约不能修改状态
        if (appointment.getStatus().equals("CANCELLED")) {
            throw new BusinessException("已取消的预约不能修改状态");
        }
        
        // 已完成的预约不能修改状态
        if (appointment.getStatus().equals("COMPLETED") && !status.equals("CANCELLED")) {
            throw new BusinessException("已完成的预约不能修改状态");
        }
        
        // 更新状态
        appointment.setStatus(status);
        appointment.setUpdatedTime(LocalDateTime.now());
        
        appointmentMapper.updateStatus(id, status, LocalDateTime.now());
    }

    @Override
    public boolean checkTimeConflict(Long serviceId, AppointmentDTO appointmentDTO) {
        LocalDateTime startTime = appointmentDTO.getAppointmentTime();
        
        // 获取服务时长
        Service service = serviceMapper.findById(serviceId);
        int duration = service.getDuration();
        
        // 计算结束时间
        LocalDateTime endTime = startTime.plusMinutes(duration);
        
        // 查询该时间段是否有其他预约
        return appointmentMapper.countByTimeRange(serviceId, startTime, endTime) > 0;
    }
    
    @Override
    public Long count() {
        AppointmentQueryDTO queryDTO = new AppointmentQueryDTO();
        return appointmentMapper.count(queryDTO);
    }
    
    /**
     * 将实体转换为DTO
     */
    private AppointmentDTO convertToDTO(Appointment appointment) {
        if (appointment == null) {
            return null;
        }
        
        AppointmentDTO dto = new AppointmentDTO();
        BeanUtils.copyProperties(appointment, dto);
        
        // 获取服务名称
        Service service = serviceMapper.findById(appointment.getServiceId());
        if (service != null) {
            dto.setServiceName(service.getName());
        }
        
        // 获取宠物名称
        Pet pet = petMapper.findById(appointment.getPetId());
        if (pet != null) {
            dto.setPetName(pet.getName());
        }
        
        // 获取用户名
        User user = userMapper.findById(appointment.getUserId());
        if (user != null) {
            dto.setUsername(user.getUsername());
        }
        
        return dto;
    }
    
    /**
     * 验证状态是否有效
     */
    private boolean isValidStatus(String status) {
        return "PENDING".equals(status) || 
               "CONFIRMED".equals(status) || 
               "COMPLETED".equals(status) || 
               "CANCELLED".equals(status);
    }
} 